﻿using System.Collections.Generic;
using DataScripter.Database;
using Moq;

namespace DataScripter.UnitTests.Factories
{
    static class DbStructureFactory
    {
        public static Mock<IDatabaseStructure> Create(string myTableName)
        {
            Mock<IDatabaseStructure> structureMock = new Mock<IDatabaseStructure>();
            Mock<ITableStructure> tableStructureMock = CreateTableStructureMock(myTableName);
            structureMock.Install(tableStructureMock);
            return structureMock;
        }

        private static void Install(this Mock<IDatabaseStructure> structureMock, Mock<ITableStructure> tableStructureMock)
        {
            structureMock.Setup(s => s.GetTable(tableStructureMock.Object.TableName)).Returns(tableStructureMock.Object);
        }

        public static Mock<IDatabaseStructure> Create(string myTableName, string dependency)
        {
            Mock<IDatabaseStructure> structureMock = new Mock<IDatabaseStructure>();

            Mock<ITableStructure> tableStructureMock = CreateTableStructureMock(myTableName);
            Mock<ITableStructure> dependentTableStructureMock = CreateTableStructureMock(dependency);

            tableStructureMock.InstallDependency(dependentTableStructureMock);

            structureMock.Install(tableStructureMock);
            structureMock.Install(dependentTableStructureMock);

            return structureMock;
        }

        private static void InstallDependency(this Mock<ITableStructure> tableStructureMock, Mock<ITableStructure> dependentTableStructureMock)
        {
            ForeignKeyInfo foreignKey = new ForeignKeyInfo("FK", "dbo", tableStructureMock.Object.TableName, "C", "dbo", dependentTableStructureMock.Object.TableName, "C");
            IList<IForeignKey> myDependencies = tableStructureMock.Object.ForeignKeys;
            myDependencies.Add(foreignKey);
            tableStructureMock.Setup(ts => ts.ForeignKeys).Returns(myDependencies);
        }

        private static Mock<ITableStructure> CreateTableStructureMock(string tableName)
        {
            Mock<ITableStructure> dependentTableStructureMock = new Mock<ITableStructure>();
            dependentTableStructureMock.Setup(ts => ts.ForeignKeys).Returns(new List<IForeignKey>());
            dependentTableStructureMock.Setup(ts => ts.TableName).Returns(tableName);
            return dependentTableStructureMock;
        }

        public static Mock<IDatabaseStructure> Create(string myTableName, IEnumerable<string> dependencies)
        {
            Mock<IDatabaseStructure> structureMock = new Mock<IDatabaseStructure>();

            Mock<ITableStructure> tableStructureMock = CreateTableStructureMock(myTableName);
            foreach (string dependency in dependencies)
            {
                Mock<ITableStructure> dependentTableStructureMock = CreateTableStructureMock(dependency);
                tableStructureMock.InstallDependency(dependentTableStructureMock);
                structureMock.Install(dependentTableStructureMock);
            }

            structureMock.Install(tableStructureMock);

            return structureMock;
        }
    }
}
